package xmsg

import (
	"reflect"
	"unsafe"

	"gitee.com/shuohe/xutils/xbuf"
)

const (
	VarType_Nil = iota
	VarType_Int
	VarType_Bytes
	VarType_String
	VarType_Marshalable
	VarType_Unmarshalable
)

type Variant struct {
	reflect.SliceHeader
	Type int
}

func (this *Variant) IsNil() bool {
	return this.Data == 0
}

func (this *Variant) AsInt() int {
	if this.Type != VarType_Int {
		panic("Variant type error.")
	}
	return int(this.Data)
}

func (this *Variant) AsBytes() []byte {
	if this.Type != VarType_Bytes {
		panic("Variant type error.")
	}
	return *(*[]byte)(unsafe.Pointer(this))
}

func (this *Variant) AsString() string {
	if this.Type != VarType_String {
		panic("Variant type error.")
	}
	return *(*string)(unsafe.Pointer(this))
}

func (this *Variant) AsMarshalable() xbuf.IMarshalable {
	if this.Type != VarType_Marshalable {
		panic("Variant type error.")
	}
	return *(*xbuf.IMarshalable)(unsafe.Pointer(this))
}

func (this *Variant) AsUnmarshalable() xbuf.IUnmarshalable {
	if this.Type != VarType_Unmarshalable {
		panic("Variant type error.")
	}
	return *(*xbuf.IUnmarshalable)(unsafe.Pointer(this))
}

func (this *Variant) SetNil() {
	this.Type = VarType_Nil
	this.Data = 0
	this.Len = 0
	this.Cap = 0
}

func (this *Variant) SetInt(data int) {
	this.Type = VarType_Int
	this.Data = uintptr(data)
	this.Len = 0
	this.Cap = 0
}

func (this *Variant) SetBytes(data []byte) {
	this.Type = VarType_Bytes
	*(*[]byte)(unsafe.Pointer(this)) = data
}

func (this *Variant) SetString(data string) {
	this.Type = VarType_String
	*(*string)(unsafe.Pointer(this)) = data
	this.Cap = 0
}

func (this *Variant) SetMarshalable(data xbuf.IMarshalable) {
	this.Type = VarType_Marshalable
	*(*xbuf.IMarshalable)(unsafe.Pointer(this)) = data
	this.Cap = 0
}

func (this *Variant) SetUnmarshalable(data xbuf.IUnmarshalable) {
	this.Type = VarType_Unmarshalable
	*(*xbuf.IUnmarshalable)(unsafe.Pointer(this)) = data
	this.Cap = 0
}
